package com.enation.app.javashop.core.trade.order.service.impl;

import com.alibaba.excel.EasyExcel;
import com.enation.app.javashop.core.excel.ExportOrderProfitVO;
import com.enation.app.javashop.core.excel.ExportOrderSkuVO;
import com.enation.app.javashop.core.member.model.dos.Member;
import com.enation.app.javashop.core.member.model.enums.CommissionTypeEnum;
import com.enation.app.javashop.core.promotion.shetuan.model.vo.OrderProfitStatisticVO;
import com.enation.app.javashop.core.promotion.shetuan.model.vo.OrderProfitVO;
import com.enation.app.javashop.core.trade.order.model.dos.OrderDO;
import com.enation.app.javashop.core.trade.order.model.dos.OrderProfitDO;
import com.enation.app.javashop.core.trade.order.model.dto.OrderProfitQueryParam;
import com.enation.app.javashop.core.trade.order.model.enums.OrderStatusEnum;
import com.enation.app.javashop.core.trade.order.model.enums.OrderTypeEnum;
import com.enation.app.javashop.core.trade.order.model.vo.OrderSkuVO;
import com.enation.app.javashop.core.trade.order.service.OrderProfitManager;
import com.enation.app.javashop.core.trade.sdk.model.OrderDetailDTO;
import com.enation.app.javashop.framework.context.ThreadContextHolder;
import com.enation.app.javashop.framework.database.DaoSupport;
import com.enation.app.javashop.framework.database.Page;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.util.BeanUtil;
import com.enation.app.javashop.framework.util.DateUtil;
import com.enation.app.javashop.framework.util.JsonUtil;
import com.enation.app.javashop.framework.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author chien
 * @since 2020-07-29
 */
@Slf4j
@Service
public class OrderProfitManagerImpl implements OrderProfitManager {

    @Autowired
    @Qualifier("tradeDaoSupport")
    private DaoSupport daoSupport;

    @Override
    public OrderProfitDO getModel(Integer id) {
        return this.daoSupport.queryForObject(OrderProfitDO.class, id);
    }

    @Override
    public void add(OrderProfitDO orderProfitDO) {
        this.daoSupport.insert(orderProfitDO);
    }

    @Override
    public void edit(OrderProfitDO orderProfitDO) {
        Map<String, Integer> map = new HashMap<>(16);
        map.put("id", orderProfitDO.getId());
        this.daoSupport.update("es_order_profit", orderProfitDO, map);
    }

    @Override
    public Page loadProfitList(OrderProfitQueryParam queryParam) {
        String timeRegex = queryParam.getType() == 0 ? "%Y%m%d" : "%Y%m";
        String sql = " SELECT FROM_UNIXTIME(create_time, ? ) AS ssTime, "+
                "	sum(orderNum) AS orderNum, sum(order_price) as orderPriceSum,sum(commissionSum) AS commissionSum "+
                " FROM(SELECT  sum(op.commission_money) AS commissionSum, count(op.order_sn) AS orderNum,"+
                "		op.order_price, op.create_time FROM es_order_profit op "+
                "		WHERE op.member_id = ? AND op.create_time >= ? AND op.create_time < ? "+
                "		AND op.commission_money > 0 GROUP BY op.order_sn "+
                "	) AS tmp  GROUP BY ssTime desc ";
        return daoSupport.queryForPage(sql, queryParam.getPageNo(), queryParam.getPageSize(), OrderProfitStatisticVO.class,
                timeRegex, queryParam.getMemberId(), queryParam.getStartTime(), queryParam.getEndTime());
    }

    @Override
    public OrderProfitStatisticVO statisticAll(OrderProfitQueryParam queryParam) {
        String sql = "SELECT sum(orderNum) AS orderNum, sum(order_price) AS orderPriceSum, "+
                "	sum(commissionSum) AS commissionSum "+
                "   FROM( SELECT count(op.order_sn) AS orderNum, sum(op.commission_money) AS commissionSum, "+
                "		op.order_price FROM es_order_profit op "+
                "		WHERE op.member_id = ? AND op.create_time >= ? "+
                "		AND op.create_time < ? AND op.commission_money > 0 "+
                "		GROUP BY op.order_sn ) AS tmp ";
        OrderProfitStatisticVO orderProfitStatisticVO = daoSupport.queryForObject(sql, OrderProfitStatisticVO.class, queryParam.getMemberId(), queryParam.getStartTime(), queryParam.getEndTime());
        return orderProfitStatisticVO.getOrderNum() == null || orderProfitStatisticVO.getOrderNum() == 0 ? new OrderProfitStatisticVO() : orderProfitStatisticVO;

    }

    @Override
    public Page queryProfitList(OrderProfitQueryParam queryParam) {
        // 查询数据列表
        StringBuffer sql = new StringBuffer(" select op.*,m.real_name as 'beneficiary_name',m.mobile as 'beneficiary_mobile' from es_order_profit op LEFT JOIN es_member m on op.member_id = m.member_id  where 1=1 ");
        List<Object> params = composeSql(queryParam, sql);
        return this.daoSupport.queryForPage(sql.toString(), queryParam.getPageNo(), queryParam.getPageSize(), OrderProfitVO.class, params.toArray());
    }
    // 查询合计佣金
    @Override
    public Double getTotalCommissionMoney(OrderProfitQueryParam queryParam){
        // 查询合计佣金
        StringBuffer sql = new StringBuffer(" select sum(commission_money)  from es_order_profit op LEFT JOIN es_distribution d on op.member_id = d.member_id LEFT JOIN es_member m on d.member_id_lv1 = m.member_id where 1=1  ");
        List<Object> params = composeSql(queryParam, sql);
        Double totalCommissionMoney;
        if(params.size() > 0 ){
            totalCommissionMoney = daoSupport.queryForDouble(sql.toString(), params.toArray());
        }else {
            totalCommissionMoney = daoSupport.queryForDouble(sql.toString());
        }
        return  totalCommissionMoney;
    }

    // 查询已结算佣金
    @Override
    public Double getSettledCommissionMoney(OrderProfitQueryParam queryParam){
        StringBuffer sql = new StringBuffer(" select sum(commission_money)  from es_order_profit op LEFT JOIN es_distribution d on op.member_id = d.member_id LEFT JOIN es_member m on d.member_id_lv1 = m.member_id where 1=1 ");
        if(StringUtil.isEmpty(queryParam.getOrderStatus())){
            sql.append(" and (op.order_status = 'ROG' OR op.order_status = 'COMPLETE') ");
        }
        List<Object> params = composeSql(queryParam, sql);
        Double settledCommissionMoney ;
        if(params.size() > 0 ){
            settledCommissionMoney = daoSupport.queryForDouble(sql.toString(), params.toArray());
        }else {
            settledCommissionMoney = daoSupport.queryForDouble(sql.toString());
        }
        return  settledCommissionMoney;
    }

    private List<Object> composeSql(OrderProfitQueryParam queryParam, StringBuffer sql) {
        List<Object> params = new ArrayList<>();
        Long startTime = queryParam.getStartTime();
        Long endTime = queryParam.getEndTime();
        // 会员Id
        Integer memberId = queryParam.getMemberId();
        if (memberId != null) {
            sql.append(" and op.member_id = ?");
            params.add(memberId);
        }

        // 开始时间
        if(startTime != null){
            sql.append(" and op.create_time >= ?");
            params.add(startTime);
        }
        // 结束时间  该查询条件在小程序中使用，平台端也要使用 采用type 进行区分 0,1 小程序查询，2平台查询
        Integer type = queryParam.getType();
        if(endTime != null){
            if(type == 2){
                sql.append(" and op.create_time <= ?");
            }else{
                sql.append(" and op.create_time < ?");
            }
            params.add(endTime);
        }

        // 订单号
        String orderSn = queryParam.getOrderSn();
        if (StringUtil.notEmpty(orderSn)) {
            sql.append(" and op.order_sn = ?");
            params.add(orderSn);
        }
        // 佣金状态
        String orderStatus = queryParam.getOrderStatus();
        if (StringUtil.notEmpty(orderStatus)) {
            sql.append(" and op.order_status = ?");
            params.add(orderStatus);
        }

        // 会员姓名
        String memberName = queryParam.getMemberName();
        if (StringUtil.notEmpty(memberName)) {
            sql.append(" and op.member_name like ?");
            params.add("%"+memberName+"%");
        }
        // 买家姓名(下单用户)
        String buyerName = queryParam.getBuyerName();
        if (StringUtil.notEmpty(buyerName)) {
            sql.append(" and op.buyer_name like ?");
            params.add("%"+buyerName+"%");
        }
        //推广方式 1直推 2间推
        Integer spreadWay = queryParam.getSpreadWay();
        if (spreadWay !=null) {
            sql.append(" and op.spread_way = ?");
            params.add(spreadWay);
        }
        // 佣金类型
        Integer commissionType = queryParam.getCommissionType();
        if (commissionType !=null) {
            sql.append(" and op.commission_type = ?");
            params.add(commissionType);
        }
        // 订单类型
        String orderType = queryParam.getOrderType();
        if (StringUtil.notEmpty(orderType)) {
            sql.append(" and op.order_type = ?");
            params.add(orderType);
        }
        // 是否查询0佣金
        Integer isZero = queryParam.getIsZero();
        if (isZero == null || isZero == 0) {
            sql.append(" and op.commission_money > 0");
        }

        //收益人姓名
        String beneficiaryName = queryParam.getBeneficiaryName();
        if (StringUtil.notEmpty(beneficiaryName)) {
            sql.append(" and m.real_name like ?");
            params.add("%"+beneficiaryName+"%");
        }

        // 收益人手机号
        String beneficiaryMobile = queryParam.getBeneficiaryMobile();
        if (StringUtil.notEmpty(beneficiaryMobile)) {
            sql.append(" and m.mobile = ?");
            params.add(beneficiaryMobile);
        }

        sql.append(" and op.commission_money > 0");
        sql.append("  order by op.create_time desc");
        return params;
    }



    @Override
    public void updateOrderProfitStatus(OrderDetailDTO orderDetailDTO) {
        List<OrderProfitDO> orderProfitList = listByOrderId(orderDetailDTO.getOrderId());
        if(orderProfitList != null && orderProfitList.size() > 0){
            String orderStatus = orderDetailDTO.getOrderStatus();
            String orderStatusText = orderDetailDTO.getOrderStatusText();
            for (OrderProfitDO orderProfitDO : orderProfitList) {
                orderProfitDO.setOrderStatus(orderStatus);
                orderProfitDO.setOrderStatusName(orderStatusText);
                if(orderStatus.equals(OrderStatusEnum.CANCELLED.name())){
                    orderProfitDO.setCancelTime(DateUtil.getDateline());
                }
                daoSupport.update(orderProfitDO, orderProfitDO.getId());
            }
        }
    }

    @Override
    public List<OrderProfitDO> listByOrderId(Integer orderId) {
        String sql = "select * from es_order_profit where order_id = ?";
        return daoSupport.queryForList(sql, OrderProfitDO.class, orderId);
    }

    @Override
    public OrderProfitDO buildOrderProfit(OrderDO orderDO, OrderDetailDTO orderDetailDTO, Integer memberId, String memberName, BigDecimal commissionRate, BigDecimal commissionMoney, CommissionTypeEnum commissionTypeEnum, String memberTypeName, Integer spreadWay, Member buyerMember) {
        String itemsJson = orderDO.getItemsJson();
        List<OrderSkuVO> skuList = JsonUtil.jsonToList(itemsJson,OrderSkuVO.class);

        OrderProfitDO orderProfitDO = new OrderProfitDO();
        orderProfitDO.setMemberId(memberId);
        orderProfitDO.setMemberName(memberName);

        orderProfitDO.setProfitNo(String.valueOf(com.enation.app.javashop.framework.util.DateUtil.getDateline()));
        orderProfitDO.setProfitName(this.getGoodsName(skuList));
        orderProfitDO.setBuyerId(orderDO.getMemberId());
        orderProfitDO.setBuyerName(buyerMember.getNickname());
        orderProfitDO.setOrderId(orderDO.getOrderId());
        orderProfitDO.setOrderSn(orderDO.getSn());
        orderProfitDO.setSellerId(orderDO.getSellerId());
        orderProfitDO.setSellerName(orderDetailDTO.getSellerName());
        orderProfitDO.setOrderPrice(BigDecimal.valueOf(orderDO.getGoodsPrice()));
        orderProfitDO.setOrderType(orderDO.getOrderType());
        orderProfitDO.setOrderTypeName(this.countOrderTypeName(orderDO.getOrderType()));
        orderProfitDO.setCommissionRate(commissionRate);
        orderProfitDO.setCommissionMoney(commissionMoney);
        orderProfitDO.setOrderStatus(orderDO.getOrderStatus());
        orderProfitDO.setOrderStatusName(orderDetailDTO.getOrderStatusText());
        orderProfitDO.setCommissionType(commissionTypeEnum.getIndex());
        orderProfitDO.setCommissionTypeName(commissionTypeEnum.getText());
        String goodsImage = skuList.get(0).getGoodsImage();
        orderProfitDO.setOrderImgs(goodsImage);
        orderProfitDO.setMemberTypeName(memberTypeName);
        orderProfitDO.setSpreadWay(spreadWay);
        orderProfitDO.setCreateTime(com.enation.app.javashop.framework.util.DateUtil.getDateline());
        return orderProfitDO;
    }

    @Override
    public void delete(Integer id) {
        this.daoSupport.delete(OrderProfitDO.class, id);
    }

    // 获取订单商品名称
    private String getGoodsName(List<OrderSkuVO> skuList){
        OrderSkuVO orderSkuVO = skuList.get(0);
        String goodsName = orderSkuVO.getName();
        if(goodsName.length() >= 20){
            goodsName = goodsName.substring(0, 17) + "...";
        }
        return goodsName;
    }


    private String countOrderTypeName(String orderType) {
        String orderTypeName = "普通订单";
        if(OrderTypeEnum.pintuan.name().equals(orderType)){
            orderTypeName = "拼团订单";
        }else if(OrderTypeEnum.shetuan.name().equals(orderType)){
            orderTypeName = "团购订单";
        }
        return orderTypeName;
    }

    @Override
    public void updateOrderProfit(Double commissionMoney, String orderSn, String memberTypeName,Integer memberId) {
        String sql = "update es_order_profit set commission_money = ? where order_sn = ?  and member_type_name =? and member_id = ?";
        daoSupport.execute(sql,commissionMoney,orderSn,memberTypeName,memberId);
    }

    @Override
    public void exportProfitList(OrderProfitQueryParam queryParam) {
        // 查询数据列表
        StringBuffer sql = new StringBuffer(" select * from es_order_profit op  where 1=1 ");
        List<Object> params = composeSql(queryParam, sql);
        Page page = this.daoSupport.queryForPage(sql.toString(), queryParam.getPageNo(), queryParam.getPageSize(), OrderProfitVO.class, params.toArray());

        List<OrderProfitVO> orderProfitList = page.getData();
        List<ExportOrderProfitVO> exportOrderProfitList = new ArrayList<>();
        for (OrderProfitVO orderProfitVO : orderProfitList) {
            ExportOrderProfitVO exportOrderProfitVO = new ExportOrderProfitVO();
            BeanUtil.copyProperties(orderProfitVO,exportOrderProfitVO);

            exportOrderProfitVO.setSpreadWay(orderProfitVO.getSpreadWay() == 1 ? "直推" : "间推");
            exportOrderProfitVO.setCommissionRate(orderProfitVO.getCommissionRate()+"%");
            Long createTime = orderProfitVO.getCreateTime();
            if(!ObjectUtils.isEmpty(createTime)){
                exportOrderProfitVO.setCreateTime(DateUtil.toString(createTime,"yyyy-MM-dd HH:mm:ss"));
            }
            Long payTime = orderProfitVO.getPayTime();
            if(!ObjectUtils.isEmpty(payTime)){
                exportOrderProfitVO.setPayTime(DateUtil.toString(payTime,"yyyy-MM-dd HH:mm:ss"));
            }
            Long cancelTime = orderProfitVO.getCancelTime();
            if(!ObjectUtils.isEmpty(cancelTime)){
                exportOrderProfitVO.setCancleTime(DateUtil.toString(cancelTime,"yyyy-MM-dd HH:mm:ss"));
            }
            exportOrderProfitList.add(exportOrderProfitVO);
        }
        // 输出
        try {
            // 1.查询装卸费明细
            HttpServletResponse response = getResponse("佣金明细列表");
            EasyExcel.write(response.getOutputStream(), ExportOrderProfitVO.class).sheet("明细列表").doWrite(exportOrderProfitList);
        } catch (IOException e) {
            throw new ServiceException("500", "导出异常");
        }
    }

    private HttpServletResponse getResponse(String fileName) {
        HttpServletResponse response = ThreadContextHolder.getHttpResponse();
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        return response;
    }
}
